package cn.mw.cmdb.service.impl;

import cn.hutool.extra.spring.SpringUtil;
import cn.mw.cmdb.entity.ModelSpecificationInfo;
import cn.mw.cmdb.entity.ModelVendorInfo;
import cn.mw.cmdb.entity.MwMacOuiInfo;
import cn.mw.cmdb.enums.OperatorTypeDescEnum;
import cn.mw.cmdb.mongoMapper.ModelMacOuiMapper;
import cn.mw.cmdb.param.*;
import cn.mw.cmdb.service.ModelMacOuiService;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.util.ExcelUtils;
import cn.mw.components.mongodb.entity.SearchParam;
import cn.mw.components.mongodb.tool.CriteriaWrapper;
import cn.mw.log.client.LogClientSimple;
import cn.mw.log.enums.BusinessLogType;
import cn.mw.log.enums.LogLevel;
import cn.mw.microMonitorCommon.constant.Constants;
import cn.mw.microMonitorCommon.security.dto.MwUser;
import cn.mw.microMonitorCommon.security.utils.SecurityUtils;
import cn.mw.microMonitorCommon.util.DateUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import com.google.common.base.Strings;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.mw.cmdb.enums.PageDescEnum.ModelMAC;
import static cn.mw.cmdb.enums.PageDescEnum.ModelManufacture;

@Slf4j
public class ModelMacOuiServiceImpl extends ModelBaseServiceImpl<MwMacOuiInfo, MacOuiIdsParam> implements ModelMacOuiService {

    public static final String ID = "macOuiService";

    private ModelMacOuiMapper modelMacOuiMapper;

    private CmdbServiceManage cmdbServiceManage;
    private LogClientSimple logClientSimple;
    public ModelMacOuiServiceImpl(ModelMacOuiMapper modelMacOuiMapper, CmdbServiceManage cmdbServiceManage) {
        this.modelMacOuiMapper = modelMacOuiMapper;
        this.cmdbServiceManage = cmdbServiceManage;
    }
    public ModelMacOuiServiceImpl() {
        this.logClientSimple = SpringUtil.getBean(LogClientSimple.class);
    }

    @Override
    public MwMacOuiInfo genObject() {
        return new MwMacOuiInfo();
    }

    @Override
    Object doAdd(MwMacOuiInfo param) throws Exception {
        modelMacOuiMapper.insert(param);
        return true;
    }

    @Override
    boolean doUpdate(MwMacOuiInfo param) throws Exception {
        Query query = new Query(CriteriaWrapper.where(MwMacOuiInfo::getId).is(param.getId()));
        Update update = CMDBTool.genMongoUpdate(param, null, null);
        CMDBTool.updateFirst(modelMacOuiMapper, query, update);
        return true;
    }

    @Override
    boolean doRemove(MwMacOuiInfo param) throws Exception {
        Query query = new Query(CriteriaWrapper.where(MwMacOuiInfo::getId).in(param.getId()));
        modelMacOuiMapper.remove(query);
        return true;
    }

    @Override
    Object doBatchAdd(Object params) {
        long time1 = System.currentTimeMillis();
        List<MwMacOuiInfo> paramList = new ArrayList<>();
        if(params instanceof List){
            paramList = (List<MwMacOuiInfo>) params;
            modelMacOuiMapper.insertAll(paramList);
        }
        long time2 = System.currentTimeMillis();
        log.info("批量新增大小：" + paramList.size() + ";耗时：" + (time2 - time1) + "ms");
        return true;
    }

    @Override
    boolean doBatchUpdate(Object params) {
        return false;
    }

    @Override
    public MwMacOuiInfo doSelectById(Object id) throws Exception {
        MwMacOuiInfo info = modelMacOuiMapper.findById(id);
        return info;
    }
    public List<MwMacOuiInfo> doSelectByIds(List<String> ids) throws Exception {
        Query query = genQueryByIds(ids);
        List<MwMacOuiInfo> list = modelMacOuiMapper.find(query);
        return list;
    }
    @Override
    List<MwMacOuiInfo> doSelectList(Object param) throws Exception {
        SearchParam searchParam = (SearchParam) param;
        Criteria criteria = genCriteria(searchParam);
        Query query = genQuery(searchParam, null);
        List<MwMacOuiInfo> ret = new ArrayList<>();
        if (searchParam.getPage() == null) {
            ret = CMDBTool.selectList(MwMacOuiInfo.class, modelMacOuiMapper, query, searchParam);
        } else {
            ret = CMDBTool.selectPageList(modelMacOuiMapper, criteria, searchParam);
        }
        return ret;
    }

    @Override
    boolean doBatchRemove(MacOuiIdsParam params) throws Exception {
        Query query = new Query(CriteriaWrapper.where(MwMacOuiInfo::getId).in(params.getIds()));
        modelMacOuiMapper.remove(query);
        return true;
    }

    @Override
    public List<String> getMacVendorByShortName(MwMacOuiInfo info) throws Exception {
        Query query = new Query(CriteriaWrapper.where(MwMacOuiInfo::getShortName).in(info.getShortName()));
        List<MwMacOuiInfo> list = modelMacOuiMapper.find(query);
        List<String> collect = list.stream().filter(s -> s.getVendor() != null).map(s -> s.getVendor()).collect(Collectors.toList());
        return collect;
    }

    @Override
    public boolean checkMacOuiName(MwMacOuiInfo info) throws Exception {
        Query query = new Query(CriteriaWrapper.where(MwMacOuiInfo::getMac).in(info.getMac()));
        List<MwMacOuiInfo> list = modelMacOuiMapper.find(query);
        if (CollectionUtils.isNotEmpty(list)) {
            return true;
        }
        return false;
    }

    @Override
    public List<MacOuiExcelImportParam> importMacOuiByExcel(MultipartFile file, HttpServletResponse response) throws Exception {
        String fileName = file.getOriginalFilename();
        MwUser user = SecurityUtils.getUser();
        String loginName = user.getUsername();
        //获取所有MacOui信息
        List<MwMacOuiInfo> mwMacOuiInfos = doSelectList(new SearchParam());
        Map<String, String> macMap = mwMacOuiInfos.stream().filter(s -> !Strings.isNullOrEmpty(s.getMac())).collect(Collectors.toMap(s -> s.getMac(), s -> s.getId(), (
                value1, value2) -> {
            return value2;
        }));
        List<MacOuiExcelImportParam> list = new ArrayList<>();
        if (null != fileName && (fileName.toLowerCase().endsWith(".xls") || fileName.toLowerCase().endsWith(".xlsx"))) {
            EasyExcel.read(file.getInputStream(), MacOuiExcelImportParam.class,
                    new MacOuiExcelImportListener(response, fileName, loginName, this, macMap,list)).sheet().doRead();
        } else {
            log.error("没有传入正确的excel文件名", file);
        }
        return list;
    }

    @Override
    public int exportMacOuiByExcel(MacOuiSearchParam param, HttpServletResponse response) throws Exception {
        int num = 0;
        ExcelWriter excelWriter = null;
        try {
            List<String> includeColumnFiledNames = new ArrayList<>(param.getHeader());
            if (org.apache.commons.collections.CollectionUtils.isEmpty(includeColumnFiledNames)) {
                includeColumnFiledNames.add(CMDBTool.getFieldName(MacOuiExcelImportParam::getMac));
                includeColumnFiledNames.add(CMDBTool.getFieldName(MacOuiExcelImportParam::getVendor));
                includeColumnFiledNames.add(CMDBTool.getFieldName(MacOuiExcelImportParam::getShortName));
                includeColumnFiledNames.add(CMDBTool.getFieldName(MacOuiExcelImportParam::getCountry));
                includeColumnFiledNames.add(CMDBTool.getFieldName(MacOuiExcelImportParam::getAddress));
            }
            excelWriter = ExcelUtils.getExcelWriter("exportModelMacOui", response, MacOuiExcelImportParam.class);
            WriteSheet sheet = EasyExcel.writerSheet(0, "sheet" + 0)
                    .includeColumnFiledNames(includeColumnFiledNames)
                    .registerWriteHandler(ExcelUtils.writeTemplateStyle())
                    .registerWriteHandler(new MacOuiColumWithStyle())
                    .build();
            List<MwMacOuiInfo> mwMacOuiInfos;
            if (param.isExportTemp()) {
                mwMacOuiInfos = new ArrayList<>();
            } else {
                param.setOperation(SearchParam.keyword);
                param.setKeywordValue("");
                mwMacOuiInfos = doSelectList(param);
            }
            excelWriter.write(mwMacOuiInfos, sheet);
            if(CollectionUtils.isNotEmpty(mwMacOuiInfos)){
                num = mwMacOuiInfos.size();
            }
            log.info("导出成功");
        } catch (IOException e) {
            log.error("导出失败{}", e);
        } finally {
            if (null != excelWriter) {
                excelWriter.finish();
            }
        }
        return num;
    }

    private class MacOuiColumWithStyle extends AbstractColumnWidthStyleStrategy {
        @Override
        protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
            if (isHead) {
                writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), 6000);
            }
        }
    }

    /**
     * 新增异常日志记录
     *
     * @param param
     */
    public void addRecordMethod(Object param) {
        String name = "";
        if (param != null && param instanceof MwMacOuiInfo) {
            MwMacOuiInfo info = (MwMacOuiInfo) param;
            name = info.getMac();
        }
        String nickName = SecurityUtils.getUser().getNickName();
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.add.getCname() + ModelMAC.getDesc(),
                        OperatorTypeDescEnum.add.getCname() + name, Constants.OperationStatus.FAILED}, LocaleContextHolder.getLocale()));
    }

    /**
     * 修改异常日志记录
     *
     * @param param
     */
    public void updateRecordMethod(Object param) {
        String name = "";
        if (param != null && param instanceof MwMacOuiInfo) {
            MwMacOuiInfo info = (MwMacOuiInfo) param;
            name = info.getMac();
        }
        String nickName = SecurityUtils.getUser().getNickName();
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.update.getCname() + ModelMAC.getDesc(),
                        OperatorTypeDescEnum.update.getCname() + name, Constants.OperationStatus.FAILED}, LocaleContextHolder.getLocale()));
    }

    /**
     * 删除异常日志记录
     *
     * @param param
     */
    private void removeRecordMethod(Object param) {
        String name = "";
        if (param != null && param instanceof MwMacOuiInfo) {
            MwMacOuiInfo info = (MwMacOuiInfo) param;
            name = info.getMac();
        }
        String nickName = SecurityUtils.getUser().getNickName();
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.remove.getCname() + ModelMAC.getDesc(),
                        OperatorTypeDescEnum.remove.getCname() + name, Constants.OperationStatus.FAILED}, LocaleContextHolder.getLocale()));

    }

    /**
     * 批量新增异常日志记录
     *
     */
    private void batchAddRecordMethod(Object params) {
        String name = "";
        if (params!=null && params instanceof List) {
            List<MwMacOuiInfo> list = (List<MwMacOuiInfo>) params;
            List<String> collect = list.stream().map(s -> s.getMac()).collect(Collectors.toList());
            name = String.join(",", collect);
        }
        String nickName = SecurityUtils.getUser().getNickName();
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.batchAdd.getCname() + ModelMAC.getDesc(),
                        OperatorTypeDescEnum.batchAdd.getCname() + name, Constants.OperationStatus.FAILED}, LocaleContextHolder.getLocale()));
    }

    /**
     * 批量修改异常日志记录
     *
     * @param param
     */
    private void batchUpdateRecordMethod(Object param) {

    }

    /**
     * 批量删除异常日志记录
     *
     */
    private void batchRemoveRecordMethod(Object params) throws Exception {
        String name = "";
        if (params != null && params instanceof MacOuiIdsParam) {
            List<String> ids = ((MacOuiIdsParam) params).getIds();
            List<MwMacOuiInfo> infos = doSelectByIds(ids);
            List<String> collect = infos.stream().map(s -> s.getMac()).collect(Collectors.toList());
            name = String.join(",", collect);
        }
        String nickName = SecurityUtils.getUser().getNickName();
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.batchRemove.getCname() + ModelMAC.getDesc(),
                        OperatorTypeDescEnum.batchRemove.getCname() + name, Constants.OperationStatus.FAILED}, LocaleContextHolder.getLocale()));

    }
}
